using MediatR;
using Dapper;
using RBAC.Domain.PurchasingManagement.PurchaseOrders;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Write.Api.Application.Command.ERP.PurchasingManagement.PurchaseArrivalNotes;

namespace RBAC.Write.Api.Application.Handler.ERP.PurchasingManagement.PurchaseArrivalNotes
{
    public class UpdatePurchaseArrivalNoteCommandHandler : IRequestHandler<UpdatePurchaseArrivalNoteCommand, APIResult<int>>
    {
        private readonly IBaseRepository<ArrivalOrderInfo> _arrivalOrderRepo;
        private readonly IDbConnectionFactory _connectionFactory;
        private readonly ILogger<UpdatePurchaseArrivalNoteCommandHandler> _logger;

        public UpdatePurchaseArrivalNoteCommandHandler(
            IBaseRepository<ArrivalOrderInfo> arrivalOrderRepo,
            IDbConnectionFactory connectionFactory,
            ILogger<UpdatePurchaseArrivalNoteCommandHandler> logger)
        {
            _arrivalOrderRepo = arrivalOrderRepo;
            _connectionFactory = connectionFactory;
            _logger = logger;
        }

        public async Task<APIResult<int>> Handle(UpdatePurchaseArrivalNoteCommand request, CancellationToken cancellationToken)
        {
            try
            {
                if (request.Id <= 0)
                {
                    return new APIResult<int> { Code = APIEnums.Fail, Msg = "无效的ID", Data = 0 };
                }

                var model = _arrivalOrderRepo.GetModel(request.Id);
                if (model == null)
                {
                    return new APIResult<int> { Code = APIEnums.Fail, Msg = "记录不存在", Data = 0 };
                }

                if (!string.IsNullOrWhiteSpace(request.DocCode))
                {
                    var exists = _arrivalOrderRepo.GetFirstOrDefault(
                        "DocCode = @DocCode AND Id <> @Id",
                        new { request.DocCode, request.Id });
                    if (exists != null)
                    {
                        return new APIResult<int> { Code = APIEnums.Fail, Msg = "单据编码已存在", Data = 0 };
                    }
                }

                // 映射更新主表
                model.DocCode = request.DocCode ?? model.DocCode;
                model.BizType = request.BizType ?? model.BizType;
                model.PurchaseOrderNo = request.PurchaseOrderNo ?? model.PurchaseOrderNo;
                model.DeliveryNote = request.DeliveryNote ?? model.DeliveryNote;
                model.DocDate = request.DocDate != default ? request.DocDate : model.DocDate;
                model.Operator = request.Operator ?? model.Operator;
                model.SupplierId = request.SupplierId ?? model.SupplierId;
                model.DocStatus = request.DocStatus ?? model.DocStatus;
                model.Auditor = request.Auditor ?? model.Auditor;
                model.Warehouse = request.Warehouse ?? model.Warehouse;
                model.BizStatus = request.BizStatus != default ? request.BizStatus : model.BizStatus;
                model.AuditDate = request.AuditDate ?? model.AuditDate;
                model.Progress = request.Progress ?? model.Progress;
                model.Remark = request.Remark ?? model.Remark;

                var affected = _arrivalOrderRepo.Update(model);

                if (affected <= 0)
                {
                    return new APIResult<int> { Code = APIEnums.Fail, Msg = "更新失败", Data = 0 };
                }

                // 如果提供了明细，则重置（先逻辑删除，再插入）
                if (request.Details != null)
                {
                    try
                    {
                        using var conn = _connectionFactory.CreateConnectionWithRetry();
                        using var tran = conn.BeginTransaction();

                        // 逻辑删除原有明细
                        var delSql = "UPDATE ArrivalOrderMaterialInfo SET IsDel = 1 WHERE ArrivalOrderId = @ArrivalOrderId";
                        conn.Execute(new CommandDefinition(delSql, new { ArrivalOrderId = request.Id }, transaction: tran));

                        if (request.Details.Any())
                        {
                            var insertSql = @"INSERT INTO ArrivalOrderMaterialInfo
                                (ArrivalOrderId, DocumentaryNumber, SupplierContractNo, MaterialCode, MaterialName, MainUnit,
                                 Quantity, BatchNo, InboundQuantity, ArrivalDescription, IsDel)
                                VALUES
                                (@ArrivalOrderId, @DocumentaryNumber, @SupplierContractNo, @MaterialCode, @MaterialName, @MainUnit,
                                 @Quantity, @BatchNo, @InboundQuantity, @ArrivalDescription, @IsDel);";

                            foreach (var d in request.Details)
                            {
                                var parameters = new
                                {
                                    ArrivalOrderId = request.Id,
                                    DocumentaryNumber = d.DocumentaryNumber,
                                    SupplierContractNo = d.SupplierContractNo,
                                    MaterialCode = d.MaterialCode,
                                    MaterialName = d.MaterialName,
                                    MainUnit = d.MainUnit,
                                    Quantity = d.Quantity,
                                    BatchNo = d.BatchNo,
                                    InboundQuantity = d.InboundQuantity,
                                    ArrivalDescription = d.ArrivalDescription,
                                    IsDel = false
                                };
                                conn.Execute(new CommandDefinition(insertSql, parameters, transaction: tran, commandTimeout: 60));
                            }
                        }

                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        _logger?.LogError(ex, "重置采购到货单明细失败: {Message}", ex.Message);
                        // 明细失败不影响主表更新结果
                    }
                }

                return new APIResult<int> { Code = APIEnums.Success, Msg = "更新成功", Data = (int)request.Id };
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "编辑采购到货单失败: {Message}", ex.Message);
                return new APIResult<int>
                {
                    Code = APIEnums.Fail,
                    Msg = "编辑采购到货单异常: " + ex.Message,
                    Data = 0
                };
            }
        }
    }
}
